package com.ruoyi.app.service.impl;

import com.ruoyi.app.domain.params.SendCodeParam;
import com.ruoyi.app.mapper.UserMapper;
import com.ruoyi.app.service.IUserService;
import com.ruoyi.app.strategy.factory.LoginFactory;
import com.ruoyi.app.strategy.factory.RegisterFactory;
import com.ruoyi.app.utils.ApiTokenServiceUtil;
import com.ruoyi.app.utils.SendCodeUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.app.domain.constants.CustomPromptConstant;
import com.ruoyi.app.domain.params.UserLoginParam;
import com.ruoyi.app.domain.params.UserRegisterParam;
import com.ruoyi.app.domain.entity.User;
import com.ruoyi.app.domain.enums.BanEnum;
import com.ruoyi.app.domain.enums.LoginTypeEnum;
import com.ruoyi.app.domain.vo.UserGetInfoVO;
import com.ruoyi.app.domain.vo.UserLoginVO;
import com.ruoyi.common.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserServiceImpl implements IUserService {

    @Value("${api.token.expireTime}")
    private Integer EXPIRE_TIME;

    private final UserMapper userMapper;

    private final ApiTokenServiceUtil apiTokenServiceUtil;

    private final RedisCache redisCache;

    private final LoginFactory loginFactory;

    private final RegisterFactory registerFactory;

    private final SendCodeUtil sendCodeUtil;

    @Override
    public UserLoginVO login(UserLoginParam userLoginParam){
        // 查询用户信息
        User user = loginFactory.login(userLoginParam);
        Optional.ofNullable(user).orElseThrow(() -> new ServiceException(CustomPromptConstant.ACCOUNT_PASSWORD_ERROR, HttpStatus.FORBIDDEN));

        // 判断账号是否已被封禁
        if (user.getBan().equals(BanEnum.TRUE.getCode())) {
            throw new ServiceException(CustomPromptConstant.ACCOUNT_BAN_ERROR, HttpStatus.FORBIDDEN);
        }

        // 构建返回参数
        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtils.copyProperties(user, userLoginVO);

        // 生成令牌
        userLoginVO.setLoginTokenVO(apiTokenServiceUtil.createToken(String.valueOf(user.getId())));

        // 放入缓存
        redisCache.setCacheObject(Constants.API_LOGIN_TOKEN_KEY + userLoginVO.getId(), userLoginVO, EXPIRE_TIME, TimeUnit.MINUTES);

        return userLoginVO;
    }

    @Override
    public void register(UserRegisterParam userRegisterParam) {
        registerFactory.register(userRegisterParam);
    }

    @Override
    public void sendCode(SendCodeParam sendCodeParam) {
        if (Objects.equals(sendCodeParam.getRegisterType(), LoginTypeEnum.EMAIL.getCode())){
            sendCodeUtil.sendEmailCode(sendCodeParam.getCode());
        }else if (Objects.equals(sendCodeParam.getRegisterType(), LoginTypeEnum.PHONE.getCode())){
            sendCodeUtil.sendPhoneCode(Long.valueOf(sendCodeParam.getCode()));
        }else {
            throw new ServiceException(CustomPromptConstant.REGISTER_TYPE_ERROR,HttpStatus.FORBIDDEN);
        }
    }

    @Override
    public UserGetInfoVO getInfoById(Long id) {
        // 查询用户信息
        User user = userMapper.selectById(id);
        Optional.ofNullable(user).orElseThrow(() -> new ServiceException(CustomPromptConstant.USER_NOT_EXIST, HttpStatus.FORBIDDEN));

        // 构建返回参数
        UserGetInfoVO userGetInfoVO = new UserGetInfoVO();
        BeanUtils.copyProperties(user, userGetInfoVO);

        return userGetInfoVO;
    }
}
